#include "list.h"

int list_insert(LIST *,const void *data,int mode);

struct node_st *find_(LIST *ptr, const void *key, list_cmp *cmp)
{
	struct node_st *current;
	for (current = ptr->head.next; current != &ptr->head; current = current->next)
	{
		if (cmp(key, current->data) == 0)    //使用由用户书写的回调函数,==0表示找到
		break;
	}
	return current;   //如果没找到则crrent = &ptr->head,而头结点的数据域正好为为空current->data = NULL;
}

//头结点的数据结构
typedef struct list_head
{
	int size;
	struct node_st head;
	int (*insert)(struct list_head *, const void *, int);
	void *(*find)(struct list_head *, const void *, list_cmp *);
	int (*delete)(struct list_head *, const void *, list_cmp *);
	int (*fetch)(struct list_head *, const void *, list_cmp *,void *);
	void (*show)(struct list_head *,list_cmp *);
}LIST;   //拎着这个头指针就行了

LIST *list_create(int initsize)
{
	LIST *new = malloc(sizeof(*new));
	if (new == NULL)
		return NULL;
	new->size = initsize;
	//new->head.data = NULL;
	new->head.pre = &new->head;
	new->head.next = &new->head;

	new->insert = list_insert;
	new->delete = list_delete;
	new->fetch = list_fetch;
	new->show = list_show;
	new->find = list_find;              //指针指向函数的入口地址
	return new;
}

//不知道用户的数据类型，用void *,且用户不希望你改他的数据，用const
//mode确定插入方式
int list_insert(LIST *ptr, const void *data, int mode)
{
	struct node_st *newnode;
	//newnode = malloc(sizeof(*newnode));
	newnode = malloc(sizeof(*newnode) + ptr->size);
	if (newnode == NULL)
		return -1;
	//newnode->data = malloc(ptr->size);
	if (newnode->data == NULL)
		return -2;
	//不确定数据类型，使用memcpy函数拷贝过来
	memcpy(newnode->data, data, ptr->size);
	if (mode == LIST_FORWARD)
	{
		newnode->pre = &ptr->head;
		newnode->next = ptr->head.next;
	}
	else if (mode == LIST_BACKWARD)
	{
		newnode->pre = ptr->head.pre;   //尾部结点的后继是头结点
		newnode->next = &ptr->head;
	}
	else
		return -3;
	//这两句是尾部插入和首部插入都要执行的
	newnode->pre->next = newnode;
	newnode->next->pre = newnode;
	return 0;
}

void list_show(LIST *ptr, list_op *op)
{
	struct node_st *current = ptr->head.next; //跳过没有数据的头结点
	while (current != &ptr->head)
	{
		op(current->data);
		current = current->next;
	}
}

int list_delete(LIST *ptr,const void * key,list_cmp * cmp)
{
	struct node_st * node;
	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;       //链表中没有要删除的
	node->pre->next = node->next;
	node->next->pre = node->pre;
	//free(node->data);
	free(node);
	return 0;
}

int list_fetch(LIST *ptr,const void * key,list_cmp *cmp,void * data)
{
	struct node_st * node;
	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return -1;
	node->pre->next = node->next;
	node->next->pre = node->pre;
	if(data != NULL)
		memcpy(data,node->data,ptr->size);  //把数据拷贝出来
	free(node->data);
	free(node);
	return 0;
}

void list_destory(LIST **ptr)
{
	struct node_st *current;
	struct node_st *next;
	for (current = (*ptr)->head.next; current != &(*ptr)->head; current = next)
	{
		next = current->next;
		//free(current->data);
		free(current);
	}
	free(*ptr);   //释放头结点
	*ptr = NULL;    //如果不使用二级指针传参而使用一级指针，则这里置为NULL没有意义,仍然会产生野指针
}

void *list_find(LIST *ptr, void *key, list_cmp * cmp)
{
	struct node_st * node;
	node = find_(ptr,key,cmp);
	if(node == &ptr->head)
		return NULL;       //人为给予空指针
	return find_(ptr,key,cmp)->data;
}